<?php
/**
 * IG_Cryptoguard_Passpod
 *
 * @author maomao.thx@gmail.com
 * @copyright Copyright (c) 2009 Green Shore (http://www.iwgame.com)
 * @version $Id: Passpod.php 735 2011-08-09 02:23:19Z mmxie $
 */
class IG_Cryptoguard_Passpod extends IG_Cryptoguard_Abstract
{
    protected $_host;

    protected $_namePrefix = '';

    protected $_algname = 'md5';

    protected $_result = null;

    private $_lang = array(
        'AUTH_SUCCESS'          => '验证成功',
        'BIND_SUCCESS'          => '绑定成功',
        'CANCEL_SUCCESS'        => '解绑成功',
        'SYNC_SUCCESS'          => '校准成功',
        'DELETE_SUCCESS'        => '删除成功',
        'QUERY_STATUS_SUCCESS'  => '查找成功',
        'QUERY_SN_SUCCESS'      => '查找成功',
        'QUERY_USER_SUCCESS'    => '查找成功',
        'REPLACE_SUCCESS'       => '更换成功',

        'BINDING_ALREADY_EXISTED'           => '账号已与该密保绑定',
        'CARDPW_ERROR'                      => '服务卡密码错误',
        'GET_CONTENTS_FAILED'               => '数据连接超时',

        'NOT_FOUND'                         => '用户与密保的绑定关系不存在',
        'NOT_SUPPORTED'                     => '当前密保不支持',

        'PASSPOD_ERROR'                     => '动态密码错误',
        'PASSPOD_USED'                      => '密码已使用过',

        'TOKEN_DISABLED'                    => '密保已被禁用',
        'TOKEN_HAS_TOO_MANY_BINDINGS'       => '该密保已同时绑定3个账号，无法绑定更多账号',
        'TOKEN_HAS_TOO_MANY_HISTORY_BINDINGS'=> '密保已有太多历史绑定',
        'TOKEN_NOT_FOUND'                   => '密保不存在',
        'TOKEN_PAYMENT_OVERDUE'             => '密保已过期',
        'TOKEN_SYNC_REQUIRED'               => '您的密保需要校准了',
        'TOKEN_UNAVAILABLE'                 => '密保不可用，已经在其他游戏绑定！',

        'USER_HAS_TOO_MANY_BINDINGS'        => '该用户绑定密保数量已满',
        'USER_NOT_FOUND'                    => '该用户未绑定密保',

        //更换密保文字提示
        'NEW_PASSPOD_ERROR'                 => '新密保的动态密码错误',
        'NEW_TOKEN_DISABLED'                => '新密保已禁用',
        'NEW_TOKEN_HAS_TOO_MANY_BINDINGS'   => '新密保已同时绑定3个账号，无法绑定更多账号',
        'NEW_TOKEN_NOT_FOUND'               => '新密保不存在',
        'NEW_TOKEN_PAYMENT_OVERDUE'         => '新密保已经过期',
        'NEW_TOKEN_UNAVAILABLE'             => '新密保不可用，已经在其他游戏绑定过！',
        'NEW_PASSPOD_USED'                  => '新密保的密码已使用过',
        'NEW_BINDING_ALREADY_EXISTED'       => '新密保与这个用户的绑定已存在',
        'NEW_TOKEN_HAS_TOO_MANY_HISTORY_BINDINGS' => '新密保已有太多历史绑定',
    );

    protected $_connectTimeout = 5;
    protected $_streamContext;

    /**
     *
     * @param string|array $config
     * @throw IG_Cryptoguard_Exception
     */
    public function __construct($config = null)
    {
        if (is_array($config)) {
            if (!isset($config['host'])) {
                throw new IG_Cryptoguard_Exception("Configuration array must have a key for 'host'");
            }

            $this->_host = $config['host'];

            if (isset($config['prefix'])) {
                $this->_namePrefix = $config['prefix'];
            }
            if (isset($config['algname'])) {
                $this->_algname = $config['algname'];
            }
        } else {
            throw new IG_Cryptoguard_Exception('$config 只允许数组类型 ');
        }

        //设置 file_get_contents 超时时间
        if (isset($config['connectTimeout'])) {
            $this->_connectTimeout = $config['connectTimeout'];
        }

    }

    protected function _response($command, $params) {
        if (!isset($this->_streamContext) && !empty($this->_connectTimeout)) {
            $this->_streamContext = stream_context_create(
               array('http' => array('timeout' => $this->_connectTimeout))
            );
        }

        $path = "/{$command}.s?" . http_build_query($params);

        if ($result = @file_get_contents($this->_host . $path, false, $this->_streamContext)) {

            $result = explode(':', $result);
            if (strpos($result[0], 'SUCCESS') !== false) {
                $this->_setMessage($result[0]);
                if (!empty($result[1])) {
                    $this->_setResult(explode(',', $result[1]));
                }
                return true;
            } else if (isset($result[1])) {
                $this->_setMessage($result[1]);
                return false;
            }
            return false;
        } else {
            $this->_setMessage('GET_CONTENTS_FAILED');
            return false;
        }
    }

    protected function _setMessage($message)
    {
        $this->_message = isset($this->_lang[$message]) ? $this->_lang[$message] : $message;
        return $this;
    }

    /**
     *
     */
    public function _setResult($result)
    {
        $this->_result = $result;
        return $this;
    }

    /**
     * 验证
     * @param string $username
     * @param string $passpod
     * @return bool
     */
    public function auth($username, $passpod)
    {
        return $this->_response('auth', array(
            'username' => $this->_namePrefix . $username,
            'passpod'  => $this->_algPasspod($passpod),
            'algname'  => $this->_algname,
        ));
    }

    /**
     * 绑定
     * @param string $username
     * @param string $passpod
     * @param int $tokensn
     * @return bool
     */
    public function bind($username, $passpod, $tokensn)
    {
        return $this->_response('bind', array(
            'username' => $this->_namePrefix . $username,
            'passpod'  => $this->_algPasspod($passpod),
            'tokensn'  => $tokensn,
            'algname'  => $this->_algname,
        ));
    }

    /**
     * 解绑
     * @param string $username
     * @param string $passpod
     * @param int $tokensn
     * @return bool
     */
    public function unbind($username, $passpod, $tokensn)
    {
        $params = array(
            'username' => $this->_namePrefix . $username,
            'tokensn'  => $tokensn,
            'algname'  => $this->_algname,
        );

        if (strlen($passpod) == 16) {
            $params['cardpw'] = $passpod;
        } else {
            $params['passpod'] = $this->_algPasspod($passpod);
        }

        return $this->_response('cancel', $params);
    }


    /**
     * 校准
     * @param string $username
     * @param string $passpod
     * @param int $tokensn
     * @return bool
     */
    public function sync($username, $passpod, $tokensn)
    {
        return $this->_response('sync', array(
            'username' => $this->_namePrefix . $username,
            'passpod'  => $this->_algPasspod($passpod),
            'tokensn'  => $tokensn,
            'algname'  => $this->_algname,
        ));
    }

    /**
     * 查询令牌已绑定的用户列表
     * @param string $tokensn
     * @return bool
     */
    public function queryuser($tokensn)
    {
        return $this->_response('queryuser', array( 'tokensn'  => $tokensn ));
    }

    /**
     * 删除
     * @param array $param
     * @return String
     */
    public function delete($username, $tokensn = '')
    {
        $params = array('username' => $username);
        if (!empty($tokensn)) {
            $params['tokensn'] = $tokensn;
        }
        return $this->_response('delete', $params);
    }

    /**
     * 查询 此方法可判断用户是否存在
     * @param array $username
     * @return String
     */
    public function querystatus($username)
    {
        return $this->_response('querystatus', array('username' => $username));
    }

    /**
     * 查询用户绑定的令牌序列号列表
     * @param String $username
     * @return String
     */
    public function querysn($username)
    {
        return $this->_response('querysn', array('username' => $username));
    }

    /**
     * 更换令牌
     */
    public function replace($username, $tokensn, $passpod, $newtokensn, $newpasspod)
    {
        $params = array(
            'username' => $this->_namePrefix . $username,
            'tokensn'  => $tokensn,
            'newtokensn' => $newtokensn,
            'newpasspod' => $this->_algPasspod($newpasspod),
            'algname'  => $this->_algname,
        );

        if (strlen($passpod) == 16) {
            $params['cardpw'] = $passpod;
        } else {
            $params['passpod'] = $passpod;
        }

        return $this->_response('replace2', $params);
    }

    protected function _algPasspod($passpod)
    {
        return $this->_algname == 'md5' ? md5($passpod) : $passpod;
    }
}